﻿namespace Jim.Http;
public class HttpHelper
{
    //默认的编码
    private Encoding encoding = Encoding.Default;
    //Post数据编码
    private Encoding postencoding = Encoding.Default;

    private HttpClient client = null;

    public async Task<HttpResult> GetHtml(HttpItem item)
    {
        // 编码
        encoding = item.Encoding;

        #region 设置请求参数

        #region handle信息

        HttpClientHandler handler = new HttpClientHandler();
        handler.SslProtocols = SslProtocols.Tls12 | SslProtocols.Tls11 | SslProtocols.Tls;
        if (item.IsGzip)
            handler.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
        // 是否启用Cookie
        handler.UseCookies = item.UseCookies;
        if (handler.UseCookies && item.CookieContainer != null)
            handler.CookieContainer = item.CookieContainer;

        // 是否执行跳转功能  
        handler.AllowAutoRedirect = item.Allowautoredirect;
        if (item.MaxAutomaticRedirections > 0)
            handler.MaxAutomaticRedirections = item.MaxAutomaticRedirections;

        //设置最大连接
        if (item.MaxConnectionsPerServer > 0)
            handler.MaxConnectionsPerServer = item.MaxConnectionsPerServer;
        #endregion

        #region 请求客户端
        // 初始化请求客户端
        client = new HttpClient(handler);
        client = new HttpClient();
        // 默认版本
        client.DefaultRequestVersion = item.DefaultRequestVersion;
        // 默认版本策略
        client.DefaultVersionPolicy = item.DefaultVersionPolicy;
        // 基础地址
        // BaseAddress = new Uri("https://api.example.com/");
        // client.GetAsync("foo/bar").Result;
        // 实际访问地址为https://api.example.com/foo/bar。
        if (!string.IsNullOrWhiteSpace(item.BaseAddress))
            client.BaseAddress = new Uri(item.BaseAddress);
        // 最大返回大小
        if (item.MaxResponseContentBufferSize > 0)
            client.MaxResponseContentBufferSize = item.MaxResponseContentBufferSize;
        // 设置超时时间
        client.Timeout = TimeSpan.FromMilliseconds(item.Timeout);
        #endregion

        #region 请求头

        // 设置Accept
        if (!string.IsNullOrEmpty(item.Accept))
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(item.Accept));
        //UserAgent客户端的访问类型，包括浏览器版本和操作系统信息
        client.DefaultRequestHeaders.UserAgent.ParseAdd(item.UserAgent);
        //来源地址
        if (!string.IsNullOrWhiteSpace(item.Referer))
            client.DefaultRequestHeaders.Referrer = new Uri(item.Referer);
        // 设置目标主机
        if (!string.IsNullOrWhiteSpace(item.Host))
            client.DefaultRequestHeaders.Host = item.Host;
        // 设置服务
        client.DefaultRequestHeaders.ExpectContinue = item.Expect100Continue;
        // 设置长链接
        if (item.KeepAlive)
            client.DefaultRequestHeaders.Connection.Add("keep-alive");
        // 设置 Authorization 头
        if (!string.IsNullOrWhiteSpace(item.AccessToken))
            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(
            "Bearer", item.AccessToken);

        // 启用gzip
        if (item.IsGzip)
            client.DefaultRequestHeaders.Add("Accept-Encoding", "gzip");
        if (!string.IsNullOrWhiteSpace(item.ContentType))
            client.DefaultRequestHeaders.Add("ContentType", item.ContentType);
        //设置Header参数
        if (item.Header != null && item.Header.Count > 0)
        {
            client.DefaultRequestHeaders.Clear();
            foreach (var kv in item.Header)
            {
                client.DefaultRequestHeaders.Add(kv.Key, kv.Value);
            }
        }
        #endregion

        //当出现“请求被中止: 未能创建 SSL/TLS 安全通道”时需要配置此属性 
        if (item.SecurityProtocol > 0)
        {
            ServicePointManager.SecurityProtocol = item.SecurityProtocol;
        }
        #endregion

        #region 请求封装 
        // 创建一个 HttpRequestMessag对象
        HttpRequestMessage request = new HttpRequestMessage(item.Method, item.URL);
        if (item.Method == HttpMethod.Post)
        {
            if (item.PostDataType == PostDataType.String && !string.IsNullOrEmpty(item.Postdata))
                request.Content = new StringContent(item.Postdata, item.Encoding, "application/json");
            if (item.PostDataType == PostDataType.Form && item.PostdataDic != null)
                request.Content = new FormUrlEncodedContent(item.PostdataDic);
            if (item.PostDataType == PostDataType.Byte && item.PostdataByte != null)
                request.Content = new ByteArrayContent(item.PostdataByte);
        }
        HttpResponseMessage response = await client.SendAsync(request);
        #endregion


        #region 返回值处理

        HttpResult result = new HttpResult();
        result.Item = item;
        if (response == null) return result;

        #region 基本返回对象    
        //获取StatusCode
        result.StatusCode = response.StatusCode;
        //获取最后访问的URl
        result.ResponseUri = response.RequestMessage?.RequestUri?.ToString();
        //获取StatusDescription
        result.StatusDescription = response.ReasonPhrase;
        //获取Headers
        result.Header = response.Headers;

        #endregion


        #region Response处理

        // 确保响应成功
        response.EnsureSuccessStatusCode();

        if (item.IsGzip)
        {
            // 读取响应内容                                            
            using (var stream = await response.Content.ReadAsStreamAsync())
            using (var gzipStream = new GZipStream(stream, CompressionMode.Decompress))
            using (var output = new MemoryStream())
            {
                await gzipStream.CopyToAsync(output);
                byte[] decompressedBytes = output.ToArray();
                if (item.ResultType == ResultType.String || item.ResultType == ResultType.StringByte)
                {
                    result.Html = item.Encoding.GetString(decompressedBytes);
                }
                else if (item.ResultType == ResultType.Byte || item.ResultType == ResultType.StringByte)
                {
                    result.ResultByte = decompressedBytes;
                }
            }
        }
        else
        {
            if (item.ResultType == ResultType.String || item.ResultType == ResultType.StringByte)
            {
                result.Html = await response.Content.ReadAsStringAsync();
            }
            else if (item.ResultType == ResultType.Byte || item.ResultType == ResultType.StringByte)
            {
                result.ResultByte = await response.Content.ReadAsByteArrayAsync();
            }
        }
        #endregion

        #region cookie处理
        // 检查响应状态码
        if (response.IsSuccessStatusCode)
        {
            //Cookie是否自动更新为请求所获取的新Cookie值 
            if (item.IsUpdateCookie)
            {
                // 将响应的 Set-Cooki键值对添加到 CookieContainer
                foreach (var header in response.Headers)
                {
                    if (header.Key.Equals("Set-Cookie"))
                    {
                        foreach (var value in header.Value)
                        {
                            handler.CookieContainer.SetCookies(response.RequestMessage.RequestUri, value);
                        }
                    }
                }
            }
        }
        else
        {
            throw new Exception($"请求失败，状态码:{response.StatusCode}");
        }
        #endregion

        //重置client为空
        if (item.IsReset)
        {
            client = null;
        }
        return result;
        #endregion
    }
}